package cn.psvmc.cxzapi.util;

import cn.psvmc.cxzapi.config.ConfigKey;
import com.aliyun.oss.*;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @Description 上传授权书到oss
 * @Author ywx
 * Date 2024/8/8 8:38
 **/
@Slf4j
public class OssService {

    /**
     * @Description 生成指定位数的随机数
     * @Date 2024/8/8 10:08
     * @Author YWX
     * @Param [length]
     * @Return java.lang.String
     **/
    public static String generateRandomAlphanumeric(int length) {
        return IntStream.range(0, length)
                        .mapToObj(i -> Character.toString(OssService.generateRandomChar()))
                        .collect(Collectors.joining());
    }

    private static char generateRandomChar() {
        int randomInt = ThreadLocalRandom.current().nextInt(62);
        if (randomInt < 26) {
            return (char) ('a' + randomInt);
        } else if (randomInt < 52) {
            return (char) ('A' + (randomInt - 26));
        } else {
            return (char) ('0' + (randomInt - 52));
        }
    }

    /**
     * @Description 上传授权书到oss
     * @Date 2024/8/8 10:10
     * @Author YWX
     * @Param [filePath]
     * @Return java.lang.String
     **/
    public static String upload(String filePath) {
        String endpoint = ConfigKey.ossEndpoint;
        String accessKeyId = ConfigKey.ossAccessKeyId;
        String accessKeySecret = ConfigKey.ossAccessKeySecret;
        String bucketName = ConfigKey.bucketName;
        String name = filePath.substring(filePath.lastIndexOf("/") + 1);
        String objectName = "approve_files/" + OssService.getYMD() + "/" + OssService.generateRandomAlphanumeric(4) + "/" + name;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            FileInputStream fis = new FileInputStream(filePath);

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode == 200) {//上传成功删除本地文件
                FileUtils.deleteFile(filePath);//删除本地文件
            }
            OssService.log.info("上传结果：{}", statusCode);

        } catch (OSSException oe) {
            OssService.log.error("OSSException Error Message:{}", oe.getErrorMessage());
        } catch (ClientException ce) {
            OssService.log.error("ClientException Error Message:{}", ce.getMessage());
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return "https://" + bucketName + "." + endpoint + "/" + objectName;
    }

    /**
     * @Description 上传文件到oss
     * @Date 2024/9/2 8:47
     * @Author YWX
     * @Param [file, firstSuffix]
     * @Return java.lang.String
     **/
    public static String uploadFile(MultipartFile file, String firstSuffix) {
        String endpoint = ConfigKey.endpoint2;
        String accessKeyId = ConfigKey.accessKeyId;
        String accessKeySecret = ConfigKey.accessKeySecret;
        String bucketName = ConfigKey.bucketName2;
        String name = file.getOriginalFilename();
        String suffix = ".png";
        if (name != null) {
            suffix = name.substring(name.lastIndexOf("."));
        }
        String objectName = firstSuffix + "/" + OssService.getYMD() + "/" + OssService.generateRandomAlphanumeric(4) + suffix;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream fis = file.getInputStream();

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode != 200) {//上传失败
                throw new ServiceException("上传文件到oss失败：" + statusCode);
            }

        } catch (Exception e) {
            OssService.log.error("上传文件到oss失败：{}", e.getMessage());
            throw new ServiceException("上传文件到oss失败：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ConfigKey.previewUrl + objectName;
    }

    /**
     * @Description 上传文件到oss
     * @Date 2024/10/4 22:49
     * @Author YWX
     * @Param [filepath, firstSuffix]
     * @Return java.lang.String
     **/
    public static String uploadFile(String filepath, String firstSuffix) {
        String endpoint = ConfigKey.endpoint2;
        String accessKeyId = ConfigKey.accessKeyId;
        String accessKeySecret = ConfigKey.accessKeySecret;
        String bucketName = ConfigKey.bucketName2;
        String suffix = ".pdf";
        if (filepath != null) {
            suffix = filepath.substring(filepath.lastIndexOf("."));
        }
        String filename = filepath.substring(filepath.lastIndexOf("/") + 1, filepath.lastIndexOf("."));
        String objectName = firstSuffix + "/" + OssService.getYMD() + "/" + filename + suffix;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream fis = new FileInputStream(filepath);

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode != 200) {//上传失败
                throw new ServiceException("上传文件到oss失败：" + statusCode);
            }

        } catch (Exception e) {
            OssService.log.error("上传文件到oss2失败：{}", e.getMessage());
            throw new ServiceException("上传文件到oss失败：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ConfigKey.previewUrl + objectName;
    }

    public static String uploadBtFile(String filepath, String objectName) {
        String endpoint = ConfigKey.endpoint2;
        String accessKeyId = ConfigKey.accessKeyId;
        String accessKeySecret = ConfigKey.accessKeySecret;
        String bucketName = ConfigKey.bucketName2;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType("image/png");
            FileInputStream fis = new FileInputStream(filepath);

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis, metadata);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode != 200) {//上传失败
                throw new ServiceException("上传半透图片到oss失败：" + statusCode);
            }

        } catch (Exception e) {
            OssService.log.error("上传半透图片到oss失败：{}", e.getMessage());
            throw new ServiceException("上传半透图片到oss失败：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ConfigKey.previewUrl + objectName;
    }

    /**
     * @Description 上传文件到oss不重命名
     * @Date 2024/9/8 21:05
     * @Author YWX
     * @Param [file, objectName]
     * @Return java.lang.String
     **/
    public static String uploadFile2(MultipartFile file, String objectName) {
        String endpoint = ConfigKey.endpoint2;
        String accessKeyId = ConfigKey.accessKeyId;
        String accessKeySecret = ConfigKey.accessKeySecret;
        String bucketName = ConfigKey.bucketName2;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream fis = file.getInputStream();

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode != 200) {//上传失败
                throw new ServiceException("上传文件到oss失败：" + statusCode);
            }

        } catch (Exception e) {
            OssService.log.error("上传文件到oss失败：{}", e.getMessage());
            throw new ServiceException("上传文件到oss失败：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ConfigKey.previewUrl + objectName;
    }

    /**
     * @Description 上传网络文件到oss
     * @Date 2024/10/14 23:30
     * @Author YWX
     * @Param [fileUrl, objectName]
     * @Return java.lang.String
     **/
    public static String uploadFile3(String fileUrl, String objectName) {
        String endpoint = ConfigKey.endpoint2;
        String accessKeyId = ConfigKey.accessKeyId;
        String accessKeySecret = ConfigKey.accessKeySecret;
        String bucketName = ConfigKey.bucketName2;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            URL url = new URL(fileUrl);
            InputStream fis = url.openStream();

            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, fis);

            // 设置该属性可以返回response。如果不设置，则返回的response为空。
            putObjectRequest.setProcess("true");
            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功，则返回200。
            int statusCode = result.getResponse().getStatusCode();
            if (statusCode != 200) {//上传失败
                throw new ServiceException("上传文件到oss失败：" + statusCode);
            }

        } catch (Exception e) {
            OssService.log.error("上传网络文件到oss失败：{}", e.getMessage());
            throw new ServiceException("上传网络文件到oss失败：" + e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ConfigKey.previewUrl + objectName;
    }

    /**
     * @Description 获取年月日时分秒字符串
     * @Date 2024/8/8 10:09
     * @Author YWX
     * @Param []
     * @Return java.lang.String
     **/
    public static String getYMD() {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(calendar.getTime());
    }

    /**
     * @Description 测试类
     * @Date 2024/8/8 10:09
     * @Author YWX
     * @Param [args]
     * @Return void
     **/
    public static void main(String[] args) {
        String path = OssService.upload("D:/school/cover.pdf");
        OssService.log.info(path);
    }
}

